Buoyancy.cs 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  1. using UnityEngine;
  2. namespace FlatKit {
  3. public class Buoyancy : MonoBehaviour {
  4. [Tooltip("The object that contains a Water material.")]
  5. public Transform water;
  6. [Space]
  7. [Tooltip("Range of probing wave height for buoyancy rotation.")]
  8. public float size = 1f;
  9. [Tooltip("Max height of buoyancy going up and down.")]
  10. public float amplitude = 1f;
  11. [Space, Tooltip("Optionally provide a separate material to get the wave parameters.")]
  12. public Material overrideWaterMaterial;
  13. private Material _material;
  14. private float _speed;
  15. private float _amplitude;
  16. private float _frequency;
  17. private float _direction;
  18. private Vector3 _originalPosition;
  19. private Quaternion _originalRotation;
  20. private void Start() {
  21. var r = water.GetComponent<Renderer>();
  22. Debug.Assert(r);
  23. _material = overrideWaterMaterial != null ? overrideWaterMaterial : r.sharedMaterial;
  24. Debug.Assert(_material);
  25. Debug.Assert(_material.HasProperty("_WaveSpeed"));
  26. _speed = _material.GetFloat("_WaveSpeed");
  27. _amplitude = _material.GetFloat("_WaveAmplitude");
  28. _frequency = _material.GetFloat("_WaveFrequency");
  29. _direction = _material.GetFloat("_WaveDirection");
  30. var t = transform;
  31. _originalPosition = t.position;
  32. _originalRotation = t.rotation;
  33. }
  34. private void Update() {
  35. var positionWS = transform.position;
  36. var positionOS = water.InverseTransformPoint(positionWS);
  37. positionWS.y = GetHeightOS(positionOS) + _originalPosition.y;
  38. transform.position = positionWS;
  39. var normal = GetNormalWS(positionOS);
  40. transform.rotation = Quaternion.FromToRotation(Vector3.up, normal) * _originalRotation;
  41. }
  42. Vector2 GradientNoiseDir(Vector2 p) {
  43. p = new Vector2(p.x % 289, p.y % 289);
  44. float x = (34 * p.x + 1) * p.x % 289 + p.y;
  45. x = (34 * x + 1) * x % 289;
  46. x = ((x / 41) % 1) * 2 - 1;
  47. return (new Vector2(x - Mathf.Floor(x + 0.5f), Mathf.Abs(x) - 0.5f)).normalized;
  48. }
  49. float GradientNoise(Vector2 p) {
  50. Vector2 ip = new Vector2(Mathf.Floor(p.x), Mathf.Floor(p.y));
  51. Vector2 fp = new Vector2(p.x % 1, p.y % 1);
  52. float d00 = Vector3.Dot(GradientNoiseDir(ip), fp);
  53. float d01 = Vector3.Dot(GradientNoiseDir(ip + Vector2.up), fp - Vector2.up);
  54. float d10 = Vector3.Dot(GradientNoiseDir(ip + Vector2.right), fp - Vector2.right);
  55. float d11 = Vector3.Dot(GradientNoiseDir(ip + Vector2.one), fp - Vector2.one);
  56. fp = fp * fp * fp * (fp * (fp * 6f - Vector2.one * 15f) + Vector2.one * 10f);
  57. return Mathf.Lerp(Mathf.Lerp(d00, d01, fp.y), Mathf.Lerp(d10, d11, fp.y), fp.x);
  58. }
  59. private Vector3 GetNormalWS(Vector3 positionOS) {
  60. Vector3 b = positionOS + Vector3.forward * size;
  61. b.y = GetHeightOS(b);
  62. Vector3 c = positionOS + Vector3.right * size;
  63. c.y = GetHeightOS(b);
  64. Vector3 n = Vector3.Cross(b - positionOS, c - positionOS).normalized;
  65. return water.TransformDirection(n);
  66. }
  67. private float SineWave(Vector3 positionOS, float offset) {
  68. // Shader:
  69. // sin(offset + _Time.z * _WaveSpeed + (pos.x * sin(offset + _WaveDirection) + pos.z *
  70. // cos(offset + _WaveDirection)) * _WaveFrequency);
  71. float timez = Time.timeSinceLevelLoad * 2f;
  72. float s = Mathf.Sin(offset + timez * _speed +
  73. (positionOS.x * Mathf.Sin(offset + _direction) + positionOS.z *
  74. Mathf.Cos(offset + _direction)) * _frequency);
  75. if (_material.IsKeywordEnabled("_WAVEMODE_POINTY")) {
  76. s = 1.0f - Mathf.Abs(s);
  77. }
  78. return s * _amplitude;
  79. }
  80. private float GetHeightOS(Vector3 positionOS) {
  81. float y = SineWave(positionOS, 0.0f);
  82. if (_material.IsKeywordEnabled("_WAVEMODE_GRID")) {
  83. y *= SineWave(positionOS, 1.57f);
  84. }
  85. y *= amplitude;
  86. return y;
  87. }
  88. }
  89. }